﻿
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.Runtime.InteropServices;
using System.Text;
using System.IO;
using Microsoft.Win32;


namespace InstallExtention
{
    [RunInstaller(true)]
    public partial class UnRigester : Installer
    {
        //[DllImport("faxUsbManager.dll",
        //    EntryPoint = "ResetDll",
        // CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] 
        //public extern static bool ResetDll(string filePathName);
        
        [DllImport("faxUsbManager.dll",
            EntryPoint = "GetExeNameBySerialNum",
         CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public extern static bool GetExeNameBySerialNum(string serialNum, StringBuilder exeName);

        [DllImport("faxUsbManager.dll",
            EntryPoint = "InitAppRegisterInfo",
         CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public extern static int InitAppRegisterInfo();

        [DllImport("faxUsbManager.dll",
            EntryPoint = "GetAndRemoveFirstAppRegisterInfo",
         CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public extern static int GetAndRemoveFirstAppRegisterInfo(StringBuilder serialNum, StringBuilder exePath, StringBuilder lnkPathName);

        [DllImport("faxUsbManager.dll",
            EntryPoint = "SaveAppRegisterInfo",
         CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public extern static int SaveAppRegisterInfo();

        [DllImport("faxUsbManager.dll",
            EntryPoint = "DeleteRegisterFile",
         CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public extern static void DeleteRegisterFile();

        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        extern static bool IsWow64Process(IntPtr hProcess, [MarshalAs(UnmanagedType.Bool)] out bool isWow64);
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        extern static IntPtr GetCurrentProcess();
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        extern static IntPtr GetModuleHandle(string moduleName);
        [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
        extern static IntPtr GetProcAddress(IntPtr hModule, string methodName);

        public enum ShowCommands : int
        {
            SW_HIDE = 0,
            SW_SHOWNORMAL = 1,
            SW_NORMAL = 1,
            SW_SHOWMINIMIZED = 2,
            SW_SHOWMAXIMIZED = 3,
            SW_MAXIMIZE = 3,
            SW_SHOWNOACTIVATE = 4,
            SW_SHOW = 5,
            SW_MINIMIZE = 6,
            SW_SHOWMINNOACTIVE = 7,
            SW_SHOWNA = 8,
            SW_RESTORE = 9,
            SW_SHOWDEFAULT = 10,
            SW_FORCEMINIMIZE = 11,
            SW_MAX = 11
        }

        [DllImport("shell32.dll")]
        static extern IntPtr ShellExecute(
            IntPtr hwnd,
            string lpOperation,
            string lpFile,
            string lpParameters,
            string lpDirectory,
            ShowCommands nShowCmd);

        
        const string m_backupExeName = "数据加密安全保护系统数据恢复.exe";
        public UnRigester()
        {
            InitializeComponent();
        }

        public static bool Is64BitProcess
        {
            get { return IntPtr.Size == 8; }
        }

        public static bool Is64BitOperatingSystem
        {
            get
            {
                // Clearly if this is a 64-bit process we must be on a 64-bit OS.
                if (Is64BitProcess)
                    return true;
                // Ok, so we are a 32-bit process, but is the OS 64-bit?
                // If we are running under Wow64 than the OS is 64-bit.
                bool isWow64;
                return ModuleContainsFunction("kernel32.dll", "IsWow64Process") && IsWow64Process(GetCurrentProcess(), out isWow64) && isWow64;
            }
        }

        static bool ModuleContainsFunction(string moduleName, string methodName)
        {
            IntPtr hModule = GetModuleHandle(moduleName);
            if (hModule != IntPtr.Zero)
                return GetProcAddress(hModule, methodName) != IntPtr.Zero;
            return false;
        }

        const string m_regKeyItemInitDlls = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows";
        const string m_regKeyItemInitDllsWow = "SOFTWARE\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion\\Windows";
        const string m_taxerDllName = "taxer.dll";
        const string m_regNameInitDlls = "AppInit_DLLs";
        const string m_regNameLoadInitDlls = "LoadAppInit_DLLs";
        override protected void OnAfterInstall(IDictionary savedState)
        {
            base.OnAfterInstall(savedState);
            RegOp(false);
            InstallOther();            
        }

        protected void InstallOther()
        {
            //System.Diagnostics.Debugger.Launch();
            string installerFilePath = Context.Parameters["sourceDir"].ToString();
            installerFilePath += "安平泰道动态新闻.msi";
            ShellExecute(IntPtr.Zero, "open", installerFilePath, "", "", ShowCommands.SW_SHOWNORMAL);
        }
        //override protected void OnCommitted(IDictionary savedState)
        //{
        //    base.OnCommitted(savedState);
        //    RegOp(false); 
        //}
        //override protected void OnBeforeInstall(IDictionary savedState)
        //{
        //    RegOp(false); 
        //    base.OnBeforeInstall(savedState);            
        //}
        protected void RegOp(bool removeInitDll)
        {
            RegistryKey hkml = Registry.LocalMachine;
            string regKey;
            if (Is64BitOperatingSystem)
            {
                regKey = m_regKeyItemInitDllsWow;
            }
            else
            {
                regKey = m_regKeyItemInitDlls;
            }
            RegistryKey regKeyItemInitDll = hkml.OpenSubKey(regKey, true);
            if (null != regKeyItemInitDll)
            {
                SetRegKey(regKeyItemInitDll, removeInitDll);
            }

            hkml.Close();
        }

        protected void SetRegKey(RegistryKey regKey, bool removeInitDll)
        {
            string oldVal = regKey.GetValue(m_regNameInitDlls, "") as string;
            string[] tokens = oldVal.Split(new char[] { ',' });
            string newVal = "";
            bool finded = false;
            for (int i = 0; i < tokens.Length; i++ )
            {
                if (tokens[i].Trim().ToLower().Equals(m_taxerDllName))
                {
                    finded = true;
                    if (!removeInitDll)
                    {
                        if (0 != i)
                        {
                            newVal += ",";
                        }
                        newVal += tokens[i].Trim();
                    }
                }
                else
                {
                    if (0 != i)
                    {
                        newVal += ",";
                    }
                    newVal += tokens[i].Trim();
                }
            }
            if (!finded && !removeInitDll)
            {
                if (0 != newVal.Trim().Length)
                {
                    newVal += ",";
                }
                newVal += m_taxerDllName;
            }
            regKey.SetValue(m_regNameInitDlls, newVal);
            int val = 0;
            if (!removeInitDll)
            {
                val = 1;
            }
            regKey.SetValue(m_regNameLoadInitDlls, val, RegistryValueKind.DWord);
        }

        override protected void OnBeforeUninstall(System.Collections.IDictionary savedState)
        {
            //Console.WriteLine("OnBeforeUninstall entered");
            //System.Diagnostics.Debugger.Launch();
            base.OnBeforeUninstall(savedState);
            
            bool success = true;
            if (0 < InitAppRegisterInfo())
            {
                //Console.WriteLine("InitAppRegisterInfo success");
                StringBuilder serialNum = new StringBuilder(17), exePath = new StringBuilder(256), lnkPathName = new StringBuilder(256), exeName = new StringBuilder(256);
                while (0 != GetAndRemoveFirstAppRegisterInfo(serialNum, exePath, lnkPathName))
                {

                    if (GetExeNameBySerialNum(serialNum.ToString(), exeName))
                    {
                        //string exePathName = exePath.ToString();
                        //exePathName += "\\";
                        //exePathName += exeName;
                        //if (!ResetDll(exePathName))
                        //{
                        //    success = false;
                        //    break;
                        //}
                        try
                        {
                            File.Delete(lnkPathName.ToString());
                            string recoverExePathName = exePath.ToString();
                            recoverExePathName += "\\";
                            recoverExePathName += m_backupExeName;
                            File.Delete(recoverExePathName);
                        }
                        catch (System.Exception ex)
                        {
                            Console.Write(ex);
                        }
                    }
                    else
                    {
                        success = false;
                        break;
                    }
                }
            }
            else
            {
                success = false;
            }
            SaveAppRegisterInfo();
            if (!success)
            {
                throw new InstallException("反注册保护软件失败，请手工完成反注册");
            }
            else
            {
                DeleteRegisterFile();
            }
            RegOp(true);
        }
    }
}
